﻿using Lucene.Net.Analysis;
using Lucene.Net.Analysis.PanGu;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using PanGu;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LuceneNet
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var db = new MainDbContext())
            {
                var list = db.Company.Take(10000).ToList();
                Create(list);
            }
            string key = Console.ReadLine();
            SearchFromIndexData(key);
        }


        public static void Create(List<Company> list)
        {
            int i = 1;
            string indexPath = @"C:\Users\zhou\Documents\visual studio 2015\Projects\LuceneNet\LuceneNet\IndexData";//索引文档保存位置        
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NativeFSLockFactory());
            bool isExist = IndexReader.IndexExists(directory); //是否存在索引库文件夹以及索引库特征文件
            if (isExist)
            {
                //如果索引目录被锁定（比如索引过程中程序异常退出或另一进程在操作索引库），则解锁
                //Q:存在问题 如果一个用户正在对索引库写操作 此时是上锁的 而另一个用户过来操作时 将锁解开了 于是产生冲突 --解决方法后续
                if (IndexWriter.IsLocked(directory))
                {
                    IndexWriter.Unlock(directory);
                }
            }
            //创建向索引库写操作对象  IndexWriter(索引目录,指定使用盘古分词进行切词,最大写入长度限制)
            //补充:使用IndexWriter打开directory时会自动对索引库文件上锁
            IndexWriter writer = new IndexWriter(directory, new PanGuAnalyzer(), !isExist, IndexWriter.MaxFieldLength.UNLIMITED);
            
            foreach (var item in list)
            {

                Document document = new Document(); //new一篇文档对象 --一条记录对应索引库中的一个文档
                //向文档中添加字段  Add(字段,值,是否保存字段原始值,是否针对该列创建索引)
                document.Add(new Field("Id", item.Id.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED));//--所有字段的值都将以字符串类型保存 因为索引库只存储字符串类型数据

                //Field.Store:表示是否保存字段原值。指定Field.Store.YES的字段在检索时才能用document.Get取出原值  //Field.Index.NOT_ANALYZED:指定不按照分词后的结果保存--是否按分词后结果保存取决于是否对该列内容进行模糊查询


                document.Add(new Field("Gongsming", item.Gongsming, Field.Store.YES, Field.Index.ANALYZED));

                //Field.Index.ANALYZED:指定文章内容按照分词后结果保存 否则无法实现后续的模糊查询 
                //WITH_POSITIONS_OFFSETS:指示不仅保存分割后的词 还保存词之间的距离

                document.Add(new Field("HangyeCn", item.HangyeCn, Field.Store.YES, Field.Index.ANALYZED));
                document.Add(new Field("CreateTime", item.HangyeCn, Field.Store.YES, Field.Index.ANALYZED));
                writer.AddDocument(document); //文档写入索引库
                Console.WriteLine(item.Gongsming);
                Console.WriteLine(i);
                i++;
            }
           
            writer.Dispose();//会自动解锁
            directory.Dispose(); //不要忘了Close，否则索引结果搜不到
        }

        /// <summary>
        /// 从索引库中检索关键字
        /// </summary>
        public static void SearchFromIndexData(string key)
        {
            string indexPath = @"C:\Users\zhou\Documents\visual studio 2015\Projects\LuceneNet\LuceneNet\IndexData";//索引文档保存位置        
            FSDirectory directory = FSDirectory.Open(new DirectoryInfo(indexPath), new NoLockFactory());
            //IndexReader reader = IndexReader.Open(directory, true);
            IndexSearcher searcher = new IndexSearcher(directory, true);
            //搜索条件
            QueryParser parser =  new QueryParser(Lucene.Net.Util.Version.LUCENE_30, "Gongsming", new PanGuAnalyzer());//一个字段查询 

            //parser = new MultiFieldQueryParser(Lucene.Net.Util.Version.LUCENE_30, new string[] { "Gongsming"}, new PanGuAnalyzer());//多个字段查询  
            Query query = parser.Parse(key);

            //foreach (var item in SplitWords("哈哈红火火红"))
            //{
            //    Console.WriteLine("分词" + item);
            //}


            TopDocs docs = searcher.Search(query, (Filter)null, int.MaxValue);
            //展示数据实体对象集合

            for (int i = 0; i < docs.ScoreDocs.Length; i++)
            {
                int docId = docs.ScoreDocs[i].Doc;//得到查询结果文档的id（Lucene内部分配的id）
                Document doc = searcher.Doc(docId);//根据文档id来获得文档对象Document

                Console.WriteLine(doc.Get("Gongsming"));
                //book.ContentDescription = doc.Get("content");//未使用高亮
                //搜索关键字高亮显示 使用盘古提供高亮插件
                Console.WriteLine(HightLight(key, doc.Get("HangyeCn")));
                Console.WriteLine(doc.Get("CreateTime"));
                Console.WriteLine("--------------------------------------------------------------");
            }
            string keya = Console.ReadLine();
            SearchFromIndexData(keya);
        }


        public static string[] SplitWords(string content)
        {
            List<string> strList = new List<string>();
            Analyzer analyzer = new PanGuAnalyzer();//指定使用盘古 PanGuAnalyzer 分词算法
            TokenStream tokenStream = analyzer.ReusableTokenStream("", new StringReader(content));
            bool hasNext = tokenStream.IncrementToken();
            Lucene.Net.Analysis.Tokenattributes.ITermAttribute iTermAttribute;
            while (hasNext)
            { //Next继续分词 直至返回null
                iTermAttribute = tokenStream.GetAttribute<Lucene.Net.Analysis.Tokenattributes.ITermAttribute>();
                strList.Add(iTermAttribute.Term);
                //strList.Add(tokenStream.ToString()); //得到分词后结果
                hasNext = tokenStream.IncrementToken();
            }
            tokenStream.CloneAttributes();
            analyzer.Close();
            return strList.ToArray();
        }

        //需要添加PanGu.HighLight.dll的引用
        /// <summary>
        /// 搜索结果高亮显示
        /// </summary>
        /// <param name="keyword"> 关键字 </param>
        /// <param name="content"> 搜索结果 </param>
        /// <returns> 高亮后结果 </returns>
        public static string HightLight(string keyword, string content)
        {
            //创建HTMLFormatter,参数为高亮单词的前后缀
            PanGu.HighLight.SimpleHTMLFormatter simpleHTMLFormatter =
                new PanGu.HighLight.SimpleHTMLFormatter("<font style=\"font-style:normal;color:#cc0000;\"><b>", "</b></font>");
            //创建 Highlighter ，输入HTMLFormatter 和 盘古分词对象Semgent
            PanGu.HighLight.Highlighter highlighter =
                            new PanGu.HighLight.Highlighter(simpleHTMLFormatter,
                            new Segment());
            //设置每个摘要段的字符数
            highlighter.FragmentSize = 1000;
            //获取最匹配的摘要段
            return highlighter.GetBestFragment(keyword, content);
        }
    }
}
